﻿// Copyright (c) 深圳云企微商网络科技有限公司. All Rights Reserved.
// 丁川 QQ：2505111990 微信：i230760 qq群:774046050 邮箱:2505111990@qq.com
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.

namespace HaoCoding.Utility
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Text;
    using System.Text.RegularExpressions;

    /// <summary>
    /// 字符串操作类
    /// </summary>
    public class StringHelper
    {
        /// <summary>
        /// 把字符串按照分隔符转换成 List
        /// </summary>
        /// <param name="str">源字符串</param>
        /// <param name="separator">分隔符</param>
        /// <param name="toLower">是否转换为小写</param>
        /// <returns></returns>
        public static List<string> GetStrArray(string str, char separator, bool toLower)
        {
            var list = new List<string>();
            var ss = str.Split(separator);
            foreach (var s in ss)
            {
                if (string.IsNullOrEmpty(s)) continue;
                var strVal = s;
                if (toLower)
                {
                    strVal = s.ToLower();
                }

                list.Add(strVal);
            }

            return list;
        }

        /// <summary>
        /// 把字符串转 按照, 分割 换为数据
        /// </summary>
        /// <param name="str">源字符串</param>
        /// <returns></returns>
        public static string[] GetStrArray(string str)
        {
            return str.Split(',');
        }

        /// <summary>
        /// 把 字符串List 按照分隔符组装成 string
        /// </summary>
        /// <param name="list">源字符串List</param>
        /// <param name="separator">分隔符</param>
        /// <returns></returns>
        public static string GetArrayStr(List<string> list, string separator)
        {
            var sb = new StringBuilder();
            for (var i = 0; i < list.Count; i++)
            {
                if (i == list.Count - 1)
                {
                    sb.Append(list[i]);
                }
                else
                {
                    sb.Append(list[i]);
                    sb.Append(separator);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// 得到数组列表以逗号分隔的字符串
        /// </summary>
        /// <param name="list">源字符串List</param>
        /// <returns></returns>
        public static string GetArrayStr(List<int> list)
        {
            var sb = new StringBuilder();
            for (var i = 0; i < list.Count; i++)
            {
                if (i == list.Count - 1)
                {
                    sb.Append(list[i].ToString());
                }
                else
                {
                    sb.Append(list[i]);
                    sb.Append(",");
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// 得到数组列表以逗号分隔的字符串
        /// </summary>
        /// <param name="list">字典列表</param>
        /// <returns></returns>
        public static string GetArrayValueStr(Dictionary<int, int> list)
        {
            var sb = new StringBuilder();
            foreach (var kvp in list)
            {
                sb.Append(kvp.Value + ",");
            }

            return list.Count > 0 ? DelLastComma(sb.ToString()) : string.Empty;
        }

        #region 删除最后一个字符之后的字符

        /// <summary>
        /// 删除最后结尾的一个逗号
        /// </summary>
        /// <param name="str">源字符串</param>
        /// <returns></returns>
        public static string DelLastComma(string str)
        {
            return str.Substring(0, str.LastIndexOf(",", StringComparison.Ordinal));
        }

        /// <summary>
        /// 删除最后结尾的指定字符
        /// </summary>
        /// <param name="str">源字符串</param>
        /// <param name="strChar">指定的</param>
        /// <returns></returns>
        public static string DelLastChar(string str, string strChar)
        {
            return str.Substring(0, str.LastIndexOf(strChar, StringComparison.Ordinal));
        }

        #endregion

        /// <summary>
        /// 转全角的函数(SBC case)
        /// </summary>
        /// <param name="input">要转换的字符串</param>
        /// <returns></returns>
        public static string ToSbc(string input)
        {
            // 半角转全角：
            var c = input.ToCharArray();
            for (var i = 0; i < c.Length; i++)
            {
                if (c[i] == 32)
                {
                    c[i] = (char)12288;
                    continue;
                }

                if (c[i] < 127)
                    c[i] = (char)(c[i] + 65248);
            }

            return new string(c);
        }

        /// <summary>
        ///  转半角的函数(SBC case)
        /// </summary>
        /// <param name="input">要转换的字符串</param>
        /// <returns></returns>
        public static string ToDbc(string input)
        {
            var c = input.ToCharArray();
            for (var i = 0; i < c.Length; i++)
            {
                if (c[i] == 12288)
                {
                    c[i] = (char)32;
                    continue;
                }

                if (c[i] > 65280 && c[i] < 65375)
                    c[i] = (char)(c[i] - 65248);
            }

            return new string(c);
        }

        /// <summary>
        /// 把字符串按照指定分隔符装成 List 去除重复
        /// </summary>
        /// <param name="oStr">源字符串</param>
        /// <param name="separator">分隔符</param>
        /// <returns></returns>
        public static List<string> GetSubStringList(string oStr, char separator)
        {
            var ss = oStr.Split(separator);
            var list = ss.Where(s => !string.IsNullOrEmpty(s) && s != separator.ToString()).ToList();

            return list;
        }

        #region 将字符串样式转换为纯字符串

        /// <summary>
        ///  将字符串样式转换为纯字符串
        /// </summary>
        /// <param name="strList">源字符串</param>
        /// <param name="splitString">分隔符</param>
        /// <returns></returns>
        public static string GetCleanStyle(string strList, string splitString)
        {
            string retrunValue;

            // 如果为空，返回空值
            if (strList == null)
            {
                retrunValue = string.Empty;
            }
            else
            {
                // 返回去掉分隔符
                var newString = strList.Replace(splitString, string.Empty);
                retrunValue = newString;
            }

            return retrunValue;
        }
        #endregion

        #region 将字符串转换为新样式

        /// <summary>
        /// 将字符串转换为新样式
        /// </summary>
        /// <param name="strList">源字符串</param>
        /// <param name="newStyle">新样式</param>
        /// <param name="splitString">分隔符</param>
        /// <param name="error">输出的错误信息</param>
        /// <returns></returns>
        public static string GetNewStyle(string strList, string newStyle, string splitString, out string error)
        {
            string returnValue;

            // 如果输入空值，返回空，并给出错误提示
            if (strList == null)
            {
                returnValue = string.Empty;
                error = "请输入需要划分格式的字符串";
            }
            else
            {
                // 检查传入的字符串长度和样式是否匹配,如果不匹配，则说明使用错误。给出错误信息并返回空值
                var strListLength = strList.Length;
                var newStyleLength = GetCleanStyle(newStyle, splitString).Length;
                if (strListLength != newStyleLength)
                {
                    returnValue = string.Empty;
                    error = "样式格式的长度与输入的字符长度不符，请重新输入";
                }
                else
                {
                    // 检查新样式中分隔符的位置
                    var lengstr = string.Empty;
                    for (var i = 0; i < newStyle.Length; i++)
                    {
                        if (newStyle.Substring(i, 1) == splitString)
                        {
                            lengstr = lengstr + "," + i;
                        }
                    }

                    if (lengstr != string.Empty)
                    {
                        lengstr = lengstr.Substring(1);
                    }

                    // 将分隔符放在新样式中的位置
                    var str = lengstr.Split(',');
                    strList = str.Aggregate(strList, (current, bb) => current.Insert(int.Parse(bb), splitString));

                    // 给出最后的结果
                    returnValue = strList;

                    // 因为是正常的输出，没有错误
                    error = string.Empty;
                }
            }

            return returnValue;
        }
        #endregion

        /// <summary>
        /// 分割字符串
        /// </summary>
        /// <param name="str">源字符串</param>
        /// <param name="splitStr">分隔符</param>
        /// <returns></returns>
        public static string[] SplitMulti(string str, string splitStr)
        {
            string[] strArray = null;
            if (!string.IsNullOrEmpty(str))
            {
                strArray = new Regex(splitStr).Split(str);
            }

            return strArray;
        }

        /// <summary>
        /// 安全格式化Sql字符串
        /// </summary>
        /// <param name="string">Sql字符串</param>
        /// <param name="isDel">true为删除，false为替换</param>
        /// <returns></returns>
        public static string SqlSafeString(string @string, bool isDel)
        {
            if (isDel)
            {
                @string = @string.Replace("'", string.Empty);
                @string = @string.Replace("\"", string.Empty);
                return @string;
            }

            @string = @string.Replace("'", "&#39;");
            @string = @string.Replace("\"", "&#34;");
            return @string;
        }

        #region 获取正确的Id，如果不是正整数，返回0

        /// <summary>
        /// 获取正确的Id，如果不是正整数，返回0
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>返回正确的整数ID，失败返回0</returns>
        public static int StrToId(string value)
        {
            return IsNumberId(value) ? int.Parse(value) : 0;
        }

        #endregion

        #region 检查一个字符串是否是纯数字构成的，一般用于查询字符串参数的有效性验证。

        /// <summary>
        /// 检查一个字符串是否是纯数字构成的，一般用于查询字符串参数的有效性验证。(0除外)
        /// </summary>
        /// <param name="value">需验证的字符串。。</param>
        /// <returns>是否合法的bool值。</returns>
        public static bool IsNumberId(string value)
        {
            return QuickValidate("^[1-9]*[0-9]*$", value);
        }
        #endregion

        #region 快速验证一个字符串是否符合指定的正则表达式。

        /// <summary>
        /// 快速验证一个字符串是否符合指定的正则表达式。
        /// </summary>
        /// <param name="express">正则表达式的内容。</param>
        /// <param name="value">需验证的字符串。</param>
        /// <returns>是否合法的bool值。</returns>
        public static bool QuickValidate(string express, string value)
        {
            if (value == null) return false;
            var myRegex = new Regex(express);
            return value.Length != 0 && myRegex.IsMatch(value);
        }
        #endregion

        #region 根据配置对指定字符串进行 MD5 加密

        /// <summary>
        /// 根据配置对指定字符串进行 MD5 加密
        /// </summary>
        /// <param name="s">要加密的字符串</param>
        /// <returns></returns>
        public static string GetMd5(string s)
        {
            using (var md5 = MD5.Create())
            {
                var result = md5.ComputeHash(Encoding.UTF8.GetBytes(s));
                var strResult = BitConverter.ToString(result);
                return strResult.Replace("-", string.Empty).ToLower().Substring(8, 16);
            }
        }
        #endregion

        #region 得到字符串长度，一个汉字长度为2

        /// <summary>
        /// 得到字符串长度，一个汉字长度为2
        /// </summary>
        /// <param name="inputString">参数字符串</param>
        /// <returns></returns>
        public static int StrLength(string inputString)
        {
            var ascii = new ASCIIEncoding();
            var tempLen = 0;
            var s = ascii.GetBytes(inputString);
            foreach (var c in s)
            {
                if (c == 63)
                    tempLen += 2;
                else
                    tempLen += 1;
            }

            return tempLen;
        }
        #endregion

        #region 截取指定长度字符串

        /// <summary>
        /// 截取指定长度字符串
        /// </summary>
        /// <param name="inputString">要处理的字符串</param>
        /// <param name="len">指定长度</param>
        /// <returns>返回处理后的字符串</returns>
        public static string ClipString(string inputString, int len)
        {
            var isShowFix = false;
            if (len % 2 == 1)
            {
                isShowFix = true;
                len--;
            }

            var ascii = new ASCIIEncoding();
            var tempLen = 0;
            var tempString = string.Empty;
            var s = ascii.GetBytes(inputString);
            for (var i = 0; i < s.Length; i++)
            {
                if (s[i] == 63)
                    tempLen += 2;
                else
                    tempLen += 1;

                try
                {
                    tempString += inputString.Substring(i, 1);
                }
                catch
                {
                    break;
                }

                if (tempLen > len)
                    break;
            }

            var bytes = Encoding.Default.GetBytes(inputString);
            if (isShowFix && bytes.Length > len)
                tempString += "…";
            return tempString;
        }
        #endregion

        #region HTML转行成TEXT

        /// <summary>
        /// HTML转行成TEXT
        /// </summary>
        /// <param name="strHtml">Html代码</param>
        /// <returns></returns>
        public static string HtmlToTxt(string strHtml)
        {
            string[] aryReg =
            {
            @"<script[^>]*?>.*?</script>",
            @"<(\/\s*)?!?((\w+:)?\w+)(\w+(\s*=?\s*(([""'])(\\[""'tbnr]|[^\7])*?\7|\w+)|.{0})|\s)*?(\/\s*)?>",
            @"([\r\n])[\s]+",
            @"&(quot|#34);",
            @"&(amp|#38);",
            @"&(lt|#60);",
            @"&(gt|#62);",
            @"&(nbsp|#160);",
            @"&(iexcl|#161);",
            @"&(cent|#162);",
            @"&(pound|#163);",
            @"&(copy|#169);",
            @"&#(\d+);",
            @"-->",
            @"<!--.*\n",
            };
            var strOutput = aryReg.Select(t => new Regex(t, RegexOptions.IgnoreCase)).Aggregate(strHtml, (current, regex) => regex.Replace(current, string.Empty));

            return strOutput;
        }
        #endregion

        #region 判断对象是否为空

        /// <summary>
        /// 判断对象是否为空，为空返回true
        /// </summary>
        /// <typeparam name="T">要验证的对象的类型</typeparam>
        /// <param name="data">要验证的对象</param>
        /// <returns></returns>
        public static bool IsNullOrEmpty<T>(T data)
        {
            // 如果为null
            if (data == null)
            {
                return true;
            }

            // 如果为""
            if (data is string && string.IsNullOrEmpty(data.ToString().Trim()))
            {
                return true;
            }

            // 如果为DBNull
            if (data is DBNull)
            {
                return true;
            }

            // 不为空
            return false;
        }

        /// <summary>
        /// 判断对象是否为空，为空返回true
        /// </summary>
        /// <param name="data">要验证的对象</param>
        /// <returns></returns>
        public static bool IsNullOrEmpty(object data)
        {
            switch (data)
            {
                // 如果为null
                case null:
                // 如果为""
                case string _ when string.IsNullOrEmpty(data.ToString().Trim()):
                // 如果为DBNull
                case DBNull _:
                    return true;
                default:
                    // 不为空
                    return false;
            }
        }
        #endregion
    }
}
